<?php
/**
* Handles the process of upgrading Scribble to a new version.
*
* Copyright (c) 2009 James Gauld <james@jamesgauld.net>
* This file is part of Scribble.
* @license http://www.scribblecms.co.uk/license.txt
*
* @package Scribble
*/
use Buan\Config;
use Buan\ExtensionManager;
use Buan\SystemLog;
class UpgradeController extends ScribbleAdminController {

	/**
	* Prepare for upgrading
	*
	* @param array Action parameters
	* @return ScribbleAdminView
	*/
	public function index($params) {

		// Init
		$view = new ScribbleAdminView();
		if(!$this->init($view)) {
			SystemLog::add('Scribble is undergoing a spot of maintenance. Please try again in a few moments.', SystemLog::INFO);
			return $view;
		}
		$view->setSource(Config::get('ext.Scribble.dir.views').'/scribble/upgrade/index.tpl.php');
		return $view;
	}

	/**
	* Rollback to the restore point that was created at the start of the updrade
	* process.
	*
	* Throws an Exception if rollback fails.
	*
	* @return void
	*/
	private function rollback() {

		// Ensure the restore point is valid
		$RP = Config::get('ext.Scribble.dir.data')."/{$_SESSION['scribble_upgrade_restorepoint']}";
		if(!is_dir($RP)) {
			throw new Exception("Restore point is invalid");
		}
	}

	/**
	* Compatability checks.
	*
	* @params array
	* @return ScribbleAdminView
	*/
	public function step1($params) {

		// Init
		$view = new ScribbleAdminView();
		if(!$this->init($view)) {
			return $view;
		}
		$view->setSource(Config::get('ext.Scribble.dir.views').'/scribble/upgrade/step-1.tpl.php');
		$view->showProceedWarning = FALSE;

		// Process
		if(!empty($_POST)) {

			// Get all registered plugins and test thier compatibility with the new
			// version of Scribble
			$plugins = ScribblePluginManager::getAll();
			$currentDataVersion = ScribbleRegistry::get('ext.Scribble.version');
			$currentScribbleVersion = Config::get('ext.Scribble.version');
			$results = array();
			foreach($plugins as $p) {
				$result = new StdClass();
				$result->pluginName = $p->getName();
				$result->isCompatible = $p->testVersionCompatibility($currentScribbleVersion['string'], $currentDataVersion['string']);
				if(!$result->isCompatible) {
					$result->infoUrl = $p->getInformationUrl();
					$view->showProceedWarning = TRUE;
				}
				$results[] = $result;
			}
			$view->results = $results;
		}

		// Result
		return $view;
	}

	/**
	* Create backups.
	*
	* @params array
	* @return ScribbleAdminView
	*/
	public function step2($params) {

		// Init
		$view = new ScribbleAdminView();
		if(!$this->init($view)) {
			return $view;
		}
		$view->setSource(Config::get('ext.Scribble.dir.views').'/scribble/upgrade/step-2.tpl.php');

		// Prepare response for Ajax calls
		$response = (object)array(
			'errorCode'=>0,
			'errorMessage'=>''
		);
		$RP = isset($_SESSION['scribble_upgrade_restorepoint']) ? preg_replace("/[\/\\\\]/", "", $_SESSION['scribble_upgrade_restorepoint']) : NULL;

		// Process: Create a restore point
		// This simply creates a folder in the data directory into which all
		// subsequent backups will be stored
		if(!empty($_POST['phase-restore-point'])) {

			// Attempt creating the folder
			$folderName = "rp-".date("dmY")."-".uniqid(rand());
			if(!mkdir(Config::get('ext.Scribble.dir.data')."/{$folderName}", 0777)) {
				$response->errorCode = 1;
				$response->errorMessage = 'Failed to create the restore point folder. Check permissions in data folder.';
			}
			else {
				$_SESSION['scribble_upgrade_restorepoint'] = $folderName;
			}
		}

		// Process: Backup database
		if(!empty($_POST['phase-db'])) {
			// TODO: Support multiple databases
		}

		// Process: Archive files
		if(!empty($_POST['phase-files'])) {

			// Create archives from uploads folder and data folder.
			// Exclude any "rp-" folders (ie. restore points) in the data folder.
			foreach(array(Config::get('ext.Scribble.uploads.dir'), Config::get('ext.Scribble.dir.data')) as $k=>$folder) {
				// TODO
			}
		}

		// Process: Plugins
		if(!empty($_POST['phase-plugins'])) {
			// TODO
		}

		// Result (AJAX response)
		if(isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
			session_write_close();
			die(json_encode($response));
		}

		// Result (UI)
		return $view;
	}

	/**
	* Apply migration routines.
	*
	* @params array
	* @return ScribbleAdminView
	*/
	public function step3($params) {

		// Init
		$view = new ScribbleAdminView();
		if(!$this->init($view)) {
			return $view;
		}
		$view->setSource(Config::get('ext.Scribble.dir.views').'/scribble/upgrade/step-3.tpl.php');
		$vFrom = ScribbleRegistry::get('ext.Scribble.version.string');
		$vTo = Config::get('ext.Scribble.version.string');
		$ext = ExtensionManager::get('Scribble');

		// Process
		if(!empty($_POST)) {
			try {
				// Patch core
				$ext->patchVersion($vTo, $vFrom);

				// Patch plugins
				$plugins = ScribblePluginManager::getAll();
				foreach($plugins as $p) {
					$p->patchVersion($vTo, $vFrom);
				}

				// Write new version to registry
				ScribbleRegistry::set('ext.Scribble.version', Config::get('ext.Scribble.version'));

				// Complete
				$view->finished = TRUE;
				$view->newVersionString = $vTo;
			}
			catch(Exception $e) {
				// Patching failed, so rollback to previous version
				try {
					$this->rollbackVersion($vFrom, $vTo);
				}
				catch(Exception $e) {
					SystemLog::add($e->getMessage(), SystemLog::WARNING);
				}
			}
		}

		// Result
		return $view;
	}
}
?>